<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <ul id="ul"></ul>
  <script>
  // 1.createDocumentFragment()方法，是用来创建一个虚拟的节点对象，或者说，是用来创建文档碎片节点。它可以包含各种类型的节点，在创建之初是空的。

  // 2.DocumentFragment节点不属于文档树，继承的parentNode属性总是null。
  // 它有一个很实用的特点，当请求把一个DocumentFragment节点插入文档树时，插入的不是DocumentFragment自身，而是它的所有子孙节点，即插入的是括号里的节点。
  // 这个特性使得DocumentFragment成了占位符，暂时存放那些一次插入文档的节点。它还有利于实现文档的剪切、复制和粘贴操作。 
  // 另外，当需要添加多个 DOM 元素时，如果先将这些元素添加到DocumentFragment中，再统一将DocumentFragment添加到页面，会减少页面渲染 DOM 的次数，效率会明显提升。

  // 3.如果使用appendChid方法将原 DOM 树中的节点添加到DocumentFragment中时，会删除原来的节点。 

    console.time()
    var ul = document.getElementById("ul");
    for (var i = 0; i < 20; i++) {
      var li = document.createElement("li");
      li.innerHTML = "index: " + i;
      ul.appendChild(li);
    }
    console.timeEnd()
    /*
      由于每一次对文档的插入都会引起重新渲染（计算元素的尺寸，显示背景，内容等），
      所以进行多次插入操作使得浏览器发生了很多次渲染，效率是比较低的。这是我们提倡
      通过减少页面的渲染来提高 DOM 操作的效率的原因。

      一个优化的方法是将要创建的元素写到一个字符串上，然后一次性写到innerHTML上，
      这种利用浏览器对innerHTML的解析确实是相比上面的多次插入快了很多。但是构造
      字符串灵活性上面比较差，很难符合创建各种各样的DOM元素的需求。

      利用DocumentFragment，可以弥补这两个方法的不足。因为文档片段存在于内存中，并
      不在DOM中，所以将子元素插入到文档片段中时不会引起页面回流（对元素位置和几何上
      的计算），因此使用DocumentFragment可以起到性能优化的作用。例如上面的代码就可
      以改成下面的片段。
    */

    console.time()
    var ul = document.getElementById("ul");
    var fragment = document.createDocumentFragment();
    for (var i = 0; i < 20; i++) {
        var li = document.createElement("li");
        li.innerHTML = "index: " + i;
        fragment.appendChild(li);
    }
    ul.appendChild(fragment);
    console.timeEnd()

  </script>
</body>
</html>